package com.lagou.edu.factory;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BeanFactory {

    private static Map<String,Object> iocMap =new HashMap<String,Object>();
    public static BeanFactory beanFactory = new BeanFactory();

    static {
      //  init();
    }

    //单例，私有化方法
    private BeanFactory(){}

    //唯一获取途径
    public static BeanFactory getInstance(){
        return beanFactory;
    }

    //获取对象
    public Object getBean(String id){
        return iocMap.get(id);
    }

    //读取配置
    public static  void init(){
        //读取文件 获取文件流
        InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
        try {

            Document document = new SAXReader().read(resourceAsStream);
            Element rootElement = document.getRootElement();//beans
            List<Element> beanList = rootElement.selectNodes("//bean");

            //实例化对象
            for (Element item : beanList) {
                String id = item.attributeValue("id");//accountDao
                String aClass = item.attributeValue("class");//com.lagou.edu.dao.impl.JdbcTemplateDaoImpl
                Class<?> clazz = Class.forName(aClass);
                Object o = clazz.newInstance();

                //把反射出来的对象保存在IOC中
                iocMap.put(id,o);
            }

            //填充关系，把含有property的父element找出来，把对应的对象set进入。
            List<Element> list = rootElement.selectNodes("//property");
            for(Element item :list){
                String name = item.attributeValue("name");
                String refClazz = item.attributeValue("ref");
                Object refObj = iocMap.get(refClazz);
                Element parentElement = item.getParent();//父级 element
                String parentId = parentElement.attributeValue("id");
                Object perantObj = iocMap.get(parentId);
                //构建方法名字
                String methodName ="set"+name;
                String aClass = parentElement.attributeValue("class");
                Class<?> aClass1 = Class.forName(aClass);
                Method setMethod = null;
                Method[] methods = aClass1.getMethods();
                for(Method m :methods){
                    if(m.getName().equals(methodName)){
                        setMethod = m;
                        break;
                    }
                }
                setMethod.invoke(perantObj, refObj);
                iocMap.put(parentId,perantObj);
                // <bean id="transactionManager" class="com.lagou.edu.utils.TransactionManager">
            }
            System.out.println("bean 封装完成"+iocMap);

        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

}
